#include<stdio.h>
#include<fcntl.h>
#include<sys/epoll.h>
#include "wrap.h"
#include<string.h>
#include<strings.h>
#include<iostream>
#include<stdio.h>
#include "../Ask/Ask.h"
#include "op.h"
#include "../threadpool/threadpool.h"

#define _IPADDR_ NULL
//#define _IPADDR_ "192.168.0.235";
#define PORT 9000
#define PTHREAD_SIZE 20
#define MAX_TASK_SIZE 20




const int EPOLL_SIZE = 1024;

void thpool(Tpool *tp,char * opstr,int fd){
	thread_addtask(tp,fd,opstr,Ask_server);
}

int main(int argc,char * argv[]){
	//thread pool
	Tpool *tp = create_threadpool(PTHREAD_SIZE,MAX_TASK_SIZE);
	printf("%p\n",tp);

	// make socket and bind port
	int lfd = tcp4bind(PORT,_IPADDR_);
	
	//listen
	Listen(lfd,128);

	//create epoll
	int epfd = epoll_create(1);
	struct epoll_event ev,evs[EPOLL_SIZE];

	ev.data.fd = lfd;
	ev.events = EPOLLIN;
	epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);
	

	while(1){
		int opnum = epoll_wait(epfd,evs,EPOLL_SIZE,-1);

		if(opnum<0){
			printf("error = 38!\n");
			perror("");
			break;
		}else if(opnum>0){
			for(int i=0;i<opnum;i++){

				printf("----------------------------------------------------------------------------\n");
				if(evs[i].data.fd == lfd && (evs[i].events & EPOLLIN) ){
					struct sockaddr_in cliaddr;
					char ip[16] = "";
					socklen_t len = sizeof(cliaddr);
					int cfd = Accept(lfd,(struct sockaddr *)&cliaddr,&len);

					printf("new client ip=%s port=%d \n",inet_ntop(AF_INET,&cliaddr.sin_addr.s_addr,ip,16),
					ntohs(cliaddr.sin_port));

					int flags = fcntl(cfd,F_GETFL);
					flags |= O_NONBLOCK;
					fcntl(cfd,F_SETFL,flags);

					ev.data.fd = cfd;
					ev.events = EPOLLIN | EPOLLET;
					epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&ev);

				}else if(evs[i].events & EPOLLIN){
					char opstr[1005] = "";
					int oplen = 0;
					while(1){
						char buf[128] = "";
						int n=read(evs[i].data.fd,buf,sizeof(buf));
						if(n<0){
							if(errno == EAGAIN){
								break;
							}
							printf("a client close ID = %d\n",iptoid(evs[i].data.fd));
							perror("");
							close(evs[i].data.fd);
							epoll_ctl(epfd,EPOLL_CTL_DEL,evs[i].data.fd,&evs[i]);
							
							break;
						}else if(n==0){
							printf("a client close ID = %d\n",iptoid(evs[i].data.fd));
							//printf("error! no data here \n");
							close(evs[i].data.fd);
							epoll_ctl(epfd,EPOLL_CTL_DEL,evs[i].data.fd,&evs[i]);
							break;
						}else{
							int buflen = strlen(buf);
							for(int j=0;j<buflen;j++){
								opstr[oplen++]= buf[j];
							}
						}
					}
					if(strcmp(opstr,"")==0)continue;
					printf("terminal recieve = %s\n",opstr);
					//write(STDOUT_FILENO,opstr.c_str(),sizeof(opstr.c_str()));
					
					thpool(tp,opstr,evs[i].data.fd);
					//Ask_server(opstr,evs[i].data.fd,reback);
					//write(evs[i].data.fd,reback,(unsigned int)sizeof(reback));
					//write(evs[i].data.fd,"\n------------------------------------\n",sizeof("\n------------------------------------\n"));
				}
				printf("-----------------------------------------------------------------------------\n");
			}
		}

	}
}
